﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yto.Common.Dependency;
using Yto.Entities;
using Yto.Entities.Record;

namespace Yto.EF
{
    public abstract class BaseDbContext : DbContext, ITransient
    {
        protected BaseDbContext() { }

        protected BaseDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
        {

        }


        public override int SaveChanges()
        {
            ApplyChanges();
            return base.SaveChanges();
        }

        public override Task<int> SaveChangesAsync()
        {
            ApplyChanges();
            return base.SaveChangesAsync();
        }

        protected virtual void ApplyChanges()
        {
            var entries = ChangeTracker.Entries().ToList();
            var userId = GetAuditUserId();

            foreach (var entry in entries)
            {
                switch (entry.State)
                {
                    case EntityState.Deleted:
                        CancelDeleteForSoftDelete(entry);
                        SetDeleteModifyProperties(entry.Entity, userId);
                        break;
                }
            }


        }

        protected virtual long? GetAuditUserId()
        {
            //if (AbpSession.UserId.HasValue &&
            //    CurrentUnitOfWorkProvider != null &&
            //    CurrentUnitOfWorkProvider.Current != null &&
            //    CurrentUnitOfWorkProvider.Current.GetTenantId() == AbpSession.TenantId)
            //{
            //    return AbpSession.UserId;
            //}

            return null;
        }

        protected virtual void CancelDeleteForSoftDelete(DbEntityEntry entry)
        {
            if (!(entry.Entity is IDelete))
            {
                return;
            }

            var softDeleteEntry = entry.Cast<IDelete>();
            softDeleteEntry.Reload();
            softDeleteEntry.State = EntityState.Modified;
            softDeleteEntry.Entity.IsDelete = true;
        }
        protected virtual void SetDeleteModifyProperties(object entityAsObj, long? userId)
        {
            if (entityAsObj is IDeletedTime)
            {
                var entity = (IDeletedTime)entityAsObj;

                if (entity.DeleteTime == null)
                {
                    entity.DeleteTime = DateTime.Now;
                }
            }
        }
    }
}
